{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 使用Sequence to Sequence网络和注意力机制进行翻译"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "本教程我们将会搭建一个网络来将法语翻译成英语。\n",
    "```\n",
    "[KEY: > input, = target, < output]\n",
    "\n",
    "> il est en train de peindre un tableau .\n",
    "= he is painting a picture .\n",
    "< he is painting a picture .\n",
    "\n",
    "> pourquoi ne pas essayer ce vin delicieux ?\n",
    "= why not try that delicious wine ?\n",
    "< why not try that delicious wine ?\n",
    "\n",
    "> elle n est pas poete mais romanciere .\n",
    "= she is not a poet but a novelist .\n",
    "< she not not a poet but a novelist .\n",
    "\n",
    "> vous etes trop maigre .\n",
    "= you re too skinny .\n",
    "< you re all alone .\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这可以通过 [Sequence to sequence network](https://arxiv.org/abs/1409.3215) 简单而又强大的 idea来实现，该实现包含两个循环神经网络，它们共同工作从而将一个序列转化为另一个序列：编码器网络将输入压缩成矢量；解码器网络将该矢量展开成新的序列。  \n",
    "\n",
    "![](https://pytorch.org/tutorials/_images/seq2seq.png)\n",
    "<center><strong>图1. Sequence to sequence 网络结构</strong>\n",
    "\n",
    "为了增强模型的表现力，我们同时引入了注意力机制，它使得解码器能够学习到在翻译某个部分的时候该给整个序列多少的注意力。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**依赖包**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from __future__ import unicode_literals, print_function, division\n",
    "from io import open\n",
    "import unicodedata\n",
    "import string\n",
    "import re\n",
    "import random\n",
    "\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "from torch import optim\n",
    "import torch.nn.functional as F\n",
    "\n",
    "device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. 加载数据文件"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "本教程的数据文件是几千个英语到法语的翻译句子对。\n",
    "\n",
    ">翻译开源下载地址:[http://www.manythings.org/anki/](http://www.manythings.org/anki/)\n",
    "\n",
    "点击[这里](https://download.pytorch.org/tutorial/data.zip)下载本教程所需的翻译文件。\n",
    "\n",
    "解压到当前目录下，得到一个 `data/eng-fra.txt`文件，该文件每一行是由 tab 分隔开的翻译对:\n",
    "```\n",
    "I am cold.   J'ai froid.\n",
    "```\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "类似于字符级RNN编码字母序列，我们仍然将源语言的每个单词编码为一个one-hot向量。与语言中可能存在的几十个字符相比，词语的量显然更大，因此编码向量要大得多。我们在这里做个小小的弊，修剪数据----每种语言我们只采用几千个单词。\n",
    "\n",
    "![](https://pytorch.org/tutorials/_images/word-encoding.png)\n",
    "<center><strong>图2. one-hot 编码示例</strong>\n",
    "\n",
    "为了编码词语，我们需要每个单词的唯一索引，以便后续网络的输入和目标的构建。为此我们使用一个名为 `Lang` 的辅助类，它具有 word$\\rightarrow$index (word2index) 和 index$\\rightarrow$word(index2word)两个字典，以及用于稍后替换稀有单词的每个单词的计数(word2count)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "SOS_token = 0\n",
    "EOS_token = 1\n",
    "\n",
    "class Lang:\n",
    "    def __init__(self, name):\n",
    "        self.name = name\n",
    "        self.word2index = {}\n",
    "        self.word2count = {}\n",
    "        self.index2word = {0: \"SOS\", 1:\"EOS\"}\n",
    "        self.n_words = 2 # Count SOS and EOS\n",
    "        \n",
    "    def addSentence(self, sentence):\n",
    "        for word in sentence.split(' '):\n",
    "            self.addWord(word)\n",
    "            \n",
    "    def addWord(self, word):\n",
    "        if word not in self.word2index:\n",
    "            self.word2index[word]=self.n_words\n",
    "            self.word2count[word]=1\n",
    "            self.index2word[self.n_words]=word\n",
    "            self.n_words +=1\n",
    "        else:\n",
    "            self.word2count[word]+=1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "文件都是Unicode编码的，我们需要简单得将字符转化为ASCII编码，全部转化为小写字母，并修剪大部分标点符号。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Turn a Unicode string to plain ASCII, thanks to \n",
    "# http://stackoverflow.com/a/518232/2809427\n",
    "def unicode2Ascii(s):\n",
    "    return ''.join(\n",
    "        c for c in unicodedata.normalize('NFD', s)\n",
    "        if unicodedata.category(c) != 'Mn'\n",
    "    )\n",
    "\n",
    "# Lowercase, trim, and remove non-letter characters\n",
    "\n",
    "def normalizeString(s):\n",
    "    s = unicode2Ascii(s.lower().strip())\n",
    "    s = re.sub(r\"([.!?])\", r\" \\1\", s)\n",
    "    s = re.sub(r\"[^a-zA-Z.!?]+\", r\" \", s)\n",
    "    return s"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "读取数据，我们将文件分割成行，进一步分割成句子对。文件是 English$\\rightarrow$其他语言 ，所以这里加上一个 `reverse` 参数，可以用来获取 其他语言$\\rightarrow$英语 的翻译对。  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def readLangs(lang1, lang2, reverse = False):\n",
    "    print(\"Reading lines...\")\n",
    "    \n",
    "    # Read the file and split into lines\n",
    "    lines = open('data/%s-%s.txt'%(lang1,lang2), encoding='utf-8').\\\n",
    "        read().strip().split('\\n')\n",
    "        \n",
    "    # Split every line into pairs and normalize\n",
    "    pairs = [[normalizeString(s) for s in l.split('\\t')] for l in lines]\n",
    "    \n",
    "    # Reverse pairs, make Lang instances\n",
    "    if reverse:\n",
    "        pairs = [list(reversed(p)) for p in pairs]\n",
    "        input_lang = Lang(lang2)\n",
    "        output_lang = Lang(lang1)\n",
    "    else:\n",
    "        input_lang = Lang(lang1)\n",
    "        output_lang = Lang(lang2)\n",
    "    return input_lang, output_lang, pairs"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "由于样本句子很多，而我们想加速训练。我们会将数据集修剪成相对简短的句子。这里的最大长度是10(包括结束标点)，同时我们会过滤出 \"我是\",\"他是\" 这种形式的句子(别忘记之前忽略的撇号,比如 \"I'm\" 这种形式)。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "MAX_LENGTH = 10\n",
    "\n",
    "eng_prefixes = (\n",
    "    \"i am\", \"i m\",\n",
    "    \"he is\", \"he s\",\n",
    "    \"she is\", \"she s\",\n",
    "    \"you are\", \"you re\",\n",
    "    \"we are\", \"we re\",\n",
    "    \"they are\", \"they re\"\n",
    ")\n",
    "\n",
    "def filterPair(p):\n",
    "    return len(p[0].split(' '))< MAX_LENGTH and \\\n",
    "           len(p[1].split(' ')) < MAX_LENGTH and \\\n",
    "           p[1].startswith(eng_prefixes)\n",
    "\n",
    "def filterPairs(pairs):\n",
    "    return [pair for pair in pairs if filterPair(pair)]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "完整的数据准备流程如下：\n",
    "- 读取文本文件，按行分割，再将每行分割成语句对\n",
    "- 归一化文本，过滤内容和长度\n",
    "- 根据滤出的句子对创建词语列表"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Reading lines...\n",
      "Read 135842 sentence pairs\n",
      "Trimmed to 11893 sentence pairs\n",
      "Counting words...\n",
      "Counted words:\n",
      "fra 4920\n",
      "eng 3228\n",
      "['tu es merveilleux .', 'you re wonderful .']\n"
     ]
    }
   ],
   "source": [
    "def prepareData(lang1, lang2, reverse=False):\n",
    "    input_lang, output_lang, pairs = readLangs(lang1, lang2, reverse)\n",
    "    print(\"Read %s sentence pairs\" % len(pairs))\n",
    "    pairs = filterPairs(pairs)\n",
    "    print(\"Trimmed to %s sentence pairs\" % len(pairs))\n",
    "    print(\"Counting words...\")\n",
    "    for pair in pairs:\n",
    "        input_lang.addSentence(pair[0])\n",
    "        output_lang.addSentence(pair[1])\n",
    "    print(\"Counted words:\")\n",
    "    print(input_lang.name, input_lang.n_words)\n",
    "    print(output_lang.name, output_lang.n_words)\n",
    "    return input_lang, output_lang, pairs\n",
    "\n",
    "input_lang, output_lang, pairs = prepareData('eng','fra', True)\n",
    "print(random.choice(pairs))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. Seq2Seq 模型"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "循环神经网络对一个序列操作，然后将其输出作为下一个子操作的输入。\n",
    "\n",
    "一个 Sequence to Sequence，或者叫 seq2seq 网络，又或者叫 编码-解码网络，包含了两个RNN部分：编码器和解码器。编码器网络将输入序列转化为单个向量，解码器读取这个向量，将其转化为序列输出。**图1** 展示了这个结构。这里我们回顾下图1：\n",
    "\n",
    "![](https://pytorch.org/tutorials/_images/seq2seq.png)\n",
    "<center><strong>图1. Sequence to sequence 网络结构</strong>\n",
    "\n",
    "与使用单个RNN的序列预测不同(单个RNN序列预测的每个输入都对应一个输出), seq2seq模型使得我们能从序列的长度和顺序中解放出来，这使得其能够成为两种语言之间相互转换的理想选择。 \n",
    "\n",
    "考虑一个句子对:\n",
    "```\n",
    "Je ne suis pas le char noir     I am not the black cat\n",
    "```\n",
    "输入句子中很多单词可以直接翻译到对应的输出句子中，但是可能会有细微的顺序变动，比如 `chat noir` 和 `black cat`。此外由于`ne/pas`结构，输入句子比输出句子多一个单词。直接通过翻译输入词语的产生正确的翻译句子是很困难的。\n",
    "\n",
    "\n",
    "使用seq2seq模型，编码器创建单个向量，在理想情况下，将输入序列的“语义”编码为单个向量---代表句子的某些N维空间中的单个点"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.1 编码器"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "seq2seq网络的编码器是一个RNN，它通过**阅读**输入句子的每个单词，来生成一些值。对每一个输入单词，编码器输出一个向量和一个隐藏状态，并且使用这个隐藏状态作为下一个单词的输入。\n",
    "![](https://pytorch.org/tutorials/_images/encoder-network.png)\n",
    "<center><strong>图3. 编码器结构</strong>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "class EncoderRNN(nn.Module):\n",
    "    def __init__(self, input_size, hidden_size):\n",
    "        super(EncoderRNN, self).__init__()\n",
    "        self.hidden_size = hidden_size\n",
    "        \n",
    "        self.embedding = nn.Embedding(input_size, hidden_size)\n",
    "        self.gru = nn.GRU(hidden_size, hidden_size)\n",
    "        \n",
    "    def forward(self,input, hidden):\n",
    "        embedded = self.embedding(input).view(1,1,-1)\n",
    "        output = embedded\n",
    "        output, hidden = self.gru(output, hidden)\n",
    "        return output, hidden\n",
    "    \n",
    "    def initHidden(self):\n",
    "        return torch.zeros(1,1, self.hidden_size, device=device)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.2 解码器"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "解码器使用编码器输出的向量作为输入，输出一串单词，从而完成翻译。\n",
    "\n",
    "#### 简单的解码器\n",
    "在最简单的解码器中我们仅仅使用编码器最后一步的输出作为输入。这个最后一步的输出有时候被称为**(上下文向量)context vector** 因为它编码了整个文本序列。这个上下文向量被用作解码器的初始隐藏状态。\n",
    "\n",
    "在解码的每一步，解码器接受一个词语和一个隐藏状态。初始的输入词语是单词开始标记`<SOS>`，初始隐藏状态是上文提到的上下文向量。\n",
    "![](https://pytorch.org/tutorials/_images/decoder-network.png)\n",
    "<center><strong>图4. 简单的解码器结构</strong>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "class DecoderRNN(nn.Module):\n",
    "    def __init__(self, hidden_size, output_size):\n",
    "        super(DecoderRNN, self).__init__()\n",
    "        self.hidden_size = hidden_size\n",
    "        \n",
    "        self.embedding = nn.Embedding(output_size, hidden_size)\n",
    "        self.gru = nn.GRU(hidden_size, hidden_size)\n",
    "        self.out = nn.Linear(hidden_size, output_size)\n",
    "        self.softmax = nn.LogSoftmax(dim=1)\n",
    "        \n",
    "    def forward(self,input, hidden):\n",
    "        output = self.embedding(input).view(1,1,-1)\n",
    "        output = F.relu(output)\n",
    "        output, hidden = self.gru(output, hidden)\n",
    "        output = self.softmax(self.out(output[0]))\n",
    "        return output, hidden\n",
    "    \n",
    "    def initHidden(self):\n",
    "        return torch.zeros(1,1, self.hidden_size, device=device)\n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我鼓励你训练和观察这个模型的结果，但为了节省空间，我们将\"直捣黄龙\"并引入注意机制。\n",
    "\n",
    "#### 注意力的解码器\n",
    "\n",
    "如果仅仅是在编码器和解码器之间传递上下文向量， 对单个向量来说，表达整个句子是很困难的。\n",
    "\n",
    "注意力机制允许解码器在解码的每一步获得一个关于原始句子的注意量(即是说，这一步的翻译需要在原始句子的不同部分投入多少的注意力)。首先我们计算一个注意力权重的集合。这些权重将和编码器的输出向量相乘来获得一个权重敏感的输出。这个步骤的结果(在代码里为`attn_applied`)应包含有关输入序列特定部分的信息，从而帮助解码器选择正确的输出字。\n",
    "\n",
    "![](https://i.imgur.com/1152PYf.png)\n",
    "<center><strong>图5. 注意力结构</strong>\n",
    "\n",
    "使用一个前馈层 `attn` 来计算注意力权重，它使用解码器的输入和隐藏状态作为输入。因为训练数据中的句子长短不一，因此要创建和训练这一层，就必须选择最长的句子长度。最大长度的句子将使用所有注意力量，而较短的句子将仅使用前几个。\n",
    "\n",
    "![](https://pytorch.org/tutorials/_images/attention-decoder-network.png)\n",
    "<center><strong>图6. 注意力解码器结构</strong>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "class AttnDecoderRNN(nn.Module):\n",
    "    def __init__(self,hidden_size,output_size, dropout_p=0.1, max_length = MAX_LENGTH):\n",
    "        super(AttnDecoderRNN, self).__init__()\n",
    "        self.hidden_size = hidden_size\n",
    "        self.output_size = output_size\n",
    "        self.dropout_p = dropout_p\n",
    "        self.max_length = max_length\n",
    "        \n",
    "        self.embedding = nn.Embedding(self.output_size, self.hidden_size)\n",
    "        self.attn = nn.Linear(self.hidden_size*2, self.max_length)\n",
    "        self.attn_combine = nn.Linear(self.hidden_size*2, self.hidden_size)\n",
    "        self.dropout = nn.Dropout(self.dropout_p)\n",
    "        self.gru = nn.GRU(self.hidden_size, self.hidden_size)\n",
    "        self.out = nn.Linear(self.hidden_size, self.output_size)\n",
    "        \n",
    "    def forward(self, input, hidden, encoder_outputs):\n",
    "        embedded = self.embedding(input).view(1,1,-1)\n",
    "        embedded = self.dropout(embedded)\n",
    "        \n",
    "        attn_weights = F.softmax(\n",
    "            self.attn(torch.cat([embedded[0],hidden[0]],1)),dim=1)\n",
    "        attn_applied = torch.bmm(attn_weights.unsqueeze(0),\n",
    "                                 encoder_outputs.unsqueeze(0))\n",
    "        \n",
    "        output = torch.cat([embedded[0], attn_applied[0]],1)\n",
    "        output = self.attn_combine(output).unsqueeze(0)\n",
    "        \n",
    "        output = F.relu(output)\n",
    "        output, hidden = self.gru(output, hidden)\n",
    "        \n",
    "        output = F.log_softmax(self.out(output[0]),dim=1)\n",
    "        return output, hidden, attn_weights\n",
    "    \n",
    "    def initHidden(self):\n",
    "        return torch.zeros(1,1, self.hidden_size, device=device)\n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "通过使用相对位置方法，还有其他形式的注意力可以解决长度限制问题。参考 [Effective Approaches to Attention-based Neural Machine Translation](https://arxiv.org/abs/1508.04025)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. 训练"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.1 准备训练数据\n",
    "\n",
    "对每个训练样本对，我们需要一个输入张量(输入句子中每个词语在词典中的位置)和目标张量(目标句子中每个词语在词典中的的位置)。在创建这些向量的同时，我们给两个都句子都加上 EOS 作为结束词"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "def indexesFromSentence(lang, sentence):\n",
    "    return [lang.word2index[word] for word in sentence.split(' ')]\n",
    "\n",
    "def tensorFromSentence(lang, sentence):\n",
    "    indexes = indexesFromSentence(lang, sentence)\n",
    "    indexes.append(EOS_token)\n",
    "    return torch.tensor(indexes, dtype=torch.long, device=device).view(-1,1)\n",
    "\n",
    "def tensorsFromPair(pair):\n",
    "    input_tensor = tensorFromSentence(input_lang, pair[0])\n",
    "    target_tensor = tensorFromSentence(output_lang, pair[1])\n",
    "    return (input_tensor, target_tensor)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.2 训练模型\n",
    "\n",
    "我们将句子输入到编码器网络中，同时跟踪其每一步的输出和最后一步的隐藏状态。然后解码器网络接受一个 `<SOS>` 作为第一步的输入，编码器最后一步的隐藏状态作为其初始隐藏状态。\n",
    "\n",
    "这里有个选择问题：关于解码器的每一步，我们到底使用目标字母直接输入，还是使用前一步的网络预测结果作为输入？\n",
    "\n",
    "**Teacher forcing** 概念：使用真实目标输出作为下一个输入，而不是使用解码器的预测作为下一个输入。使用**teacher forcing**可以使网络更快地收敛，但是当受过训练的网络被运用时，它可能表现出不稳定性。\n",
    "\n",
    "你可以观察下网络的输出，读起来看似语法相关，但是实际上远离正确的翻译---直觉上网络学到了如何表示输出语法，并且一旦'Teacher'告诉它前面几个单词，它就会“提取”含义，但它还没有正确地学习如何从翻译中创建句子。  \n",
    "\n",
    "由于PyTorch的autograd为我们提供了自由度，我们可以随意选择使用teacher forcing或不使用通过简单的if语句。将teacher_forcing_ratio来控制使用的概率"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "teacher_forcing_ratio = 0.5\n",
    "\n",
    "def train(input_tensor, target_tensor, encoder, decoder, encoder_optimizer, decoder_optimizer, criterion, max_length = MAX_LENGTH):\n",
    "    encoder_hidden = encoder.initHidden()\n",
    "    \n",
    "    encoder_optimizer.zero_grad()\n",
    "    decoder_optimizer.zero_grad()\n",
    "    \n",
    "    input_length = input_tensor.size(0)\n",
    "    target_length = target_tensor.size(0)\n",
    "    \n",
    "    encoder_outputs = torch.zeros(max_length, encoder.hidden_size, device=device)\n",
    "    \n",
    "    loss = 0\n",
    "    \n",
    "    for ei in range(input_length):\n",
    "        encoder_output, encoder_hidden = encoder(input_tensor[ei], encoder_hidden)\n",
    "        encoder_outputs[ei]=encoder_output[0,0]\n",
    "        \n",
    "    decoder_input = torch.tensor([[SOS_token]], device=device)\n",
    "    \n",
    "    decoder_hidden = encoder_hidden\n",
    "    \n",
    "    use_teacher_forcing = True if random.random() < teacher_forcing_ratio else False\n",
    "    \n",
    "    if use_teacher_forcing:\n",
    "        # Teacher forcing: Feed the targer as the next input\n",
    "        for di in range(target_length):\n",
    "            decoder_output, decoder_hidden, decoder_attention = decoder(\n",
    "                decoder_input, decoder_hidden, encoder_outputs)\n",
    "            loss+=criterion(decoder_output, target_tensor[di])\n",
    "            decoder_input = target_tensor[di]   # Teacher forcing\n",
    "            \n",
    "    else:\n",
    "        # Without teaching forcing: use its own predictions as the next input\n",
    "        for di in range(target_length):\n",
    "            decoder_output, decoder_hidden, decoder_attention = decoder(\n",
    "                decoder_input, decoder_hidden, encoder_outputs)\n",
    "            topv, topi = decoder_output.topk(1)\n",
    "            decoder_input = topi.squeeze().detach() # detach from history as input\n",
    "            \n",
    "            loss+=criterion(decoder_output, target_tensor[di])\n",
    "            if decoder_input.item()==EOS_token:\n",
    "                break\n",
    "                \n",
    "    loss.backward()\n",
    "    encoder_optimizer.step()\n",
    "    decoder_optimizer.step()\n",
    "    \n",
    "    return loss.item() / target_length"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "下面是一个辅助函数，用于打印经过的时间和估计的剩余时间，通过给定的当前时间和进度％。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import time\n",
    "import math\n",
    "\n",
    "\n",
    "def asMinutes(s):\n",
    "    m = math.floor(s / 60)\n",
    "    s -= m * 60\n",
    "    return '%dm %ds' % (m, s)\n",
    "\n",
    "\n",
    "def timeSince(since, percent):\n",
    "    now = time.time()\n",
    "    s = now - since\n",
    "    es = s / (percent)\n",
    "    rs = es - s\n",
    "    return '%s (- %s)' % (asMinutes(s), asMinutes(rs))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "完整的训练流程如下：\n",
    "- 计时器打开\n",
    "- 初始化优化器和评估函数\n",
    "- 创建训练对\n",
    "- 开始跟踪损失\n",
    "\n",
    "然后我们会多次调用 `train` ，间断打印进度（例子的百分比，到目前为止的时间，估计的时间）和平均损失。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def trainIters(encoder, decoder, n_iters, print_every=1000, plot_every=1000, learning_rate=0.01):\n",
    "    start = time.time()\n",
    "    plot_losses=[]\n",
    "    print_loss_total = 0  # Reset every print_every\n",
    "    plot_loss_total = 0   # Reset every plot_every\n",
    "    \n",
    "    encoder_optimizer = optim.SGD(encoder.parameters(), lr=learning_rate)\n",
    "    decoder_optimizer = optim.SGD(decoder.parameters(), lr=learning_rate)\n",
    "    training_pairs = [tensorsFromPair(random.choice(pairs)) for i in range(n_iters)]\n",
    "    \n",
    "    criterion = nn.NLLLoss()\n",
    "    \n",
    "    for iter in range(1, n_iters+1):\n",
    "        training_pair = training_pairs[iter-1]\n",
    "        input_tensor = training_pair[0]\n",
    "        target_tensor = training_pair[1]\n",
    "        \n",
    "        loss = train(input_tensor, target_tensor, encoder, decoder, encoder_optimizer, decoder_optimizer, criterion)\n",
    "        \n",
    "        print_loss_total+=loss\n",
    "        plot_loss_total+=loss\n",
    "        \n",
    "        if iter % print_every == 0:\n",
    "            print_loss_avg = print_loss_total / print_every\n",
    "            print_loss_total = 0\n",
    "            print('%s (%d %d%%) %.4f' % (timeSince(start, iter / n_iters),\n",
    "                                         iter, iter / n_iters * 100, print_loss_avg))\n",
    "\n",
    "        if iter % plot_every == 0:\n",
    "            plot_loss_avg = plot_loss_total / plot_every\n",
    "            plot_losses.append(plot_loss_avg)\n",
    "            plot_loss_total = 0\n",
    "\n",
    "    showPlot(plot_losses)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.3 可视化结果"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "plt.switch_backend('agg')\n",
    "import matplotlib.ticker as ticker\n",
    "import numpy as np\n",
    "\n",
    "\n",
    "def showPlot(points):\n",
    "    plt.figure()\n",
    "    fig, ax = plt.subplots()\n",
    "    # this locator puts ticks at regular intervals\n",
    "    loc = ticker.MultipleLocator(base=0.2)\n",
    "    ax.yaxis.set_major_locator(loc)\n",
    "    plt.plot(points)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4. 评估"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "评估与训练大致相同，但没有目标，因此我们只需将解码器的预测反馈给每个步骤。每次它预测一个单词时我们都会将它添加到输出字符串中，如果它预测了EOS标记，我们就会停止。我们还存储解码器的注意力输出以供稍后显示。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "def evaluate(encoder, decoder, sentence, max_length=MAX_LENGTH):\n",
    "    with torch.no_grad():\n",
    "        input_tensor = tensorFromSentence(input_lang, sentence)\n",
    "        input_length = input_tensor.size()[0]\n",
    "        encoder_hidden = encoder.initHidden()\n",
    "\n",
    "        encoder_outputs = torch.zeros(max_length, encoder.hidden_size, device=device)\n",
    "\n",
    "        for ei in range(input_length):\n",
    "            encoder_output, encoder_hidden = encoder(input_tensor[ei],\n",
    "                                                     encoder_hidden)\n",
    "            encoder_outputs[ei] += encoder_output[0, 0]\n",
    "\n",
    "        decoder_input = torch.tensor([[SOS_token]], device=device)  # SOS\n",
    "\n",
    "        decoder_hidden = encoder_hidden\n",
    "\n",
    "        decoded_words = []\n",
    "        decoder_attentions = torch.zeros(max_length, max_length)\n",
    "\n",
    "        for di in range(max_length):\n",
    "            decoder_output, decoder_hidden, decoder_attention = decoder(\n",
    "                decoder_input, decoder_hidden, encoder_outputs)\n",
    "            decoder_attentions[di] = decoder_attention.data\n",
    "            topv, topi = decoder_output.data.topk(1)\n",
    "            if topi.item() == EOS_token:\n",
    "                decoded_words.append('<EOS>')\n",
    "                break\n",
    "            else:\n",
    "                decoded_words.append(output_lang.index2word[topi.item()])\n",
    "\n",
    "            decoder_input = topi.squeeze().detach()\n",
    "\n",
    "        return decoded_words, decoder_attentions[:di + 1]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " 我们可以从训练集中评估随机句子并打印输入，目标和输出以做出一些主观质量判断：\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def evaluateRandomly(encoder, decoder, n=10):\n",
    "    for i in range(n):\n",
    "        pair = random.choice(pairs)\n",
    "        print('>', pair[0])\n",
    "        print('=', pair[1])\n",
    "        output_words, attentions = evaluate(encoder, decoder, pair[0])\n",
    "        output_sentence = ' '.join(output_words)\n",
    "        print('<', output_sentence)\n",
    "        print('')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5. 训练与评估"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "有了所有这些辅助函数（它看起来像是额外的工作，但它使得更容易运行多个实验）我们实际上可以初始化网络并开始训练。 \n",
    "\n",
    "请记住，输入句子被严重过滤。对于这个小数据集，我们可以使用256个隐藏节点和单个GRU层的相对较小的网络。在MacBook CPU上大约40分钟后，我们将得到一些合理的结果。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3m 53s (- 54m 26s) (5000 6%) 3.0454\n",
      "7m 35s (- 49m 23s) (10000 13%) 2.4611\n",
      "11m 4s (- 44m 16s) (15000 20%) 2.1786\n",
      "14m 31s (- 39m 55s) (20000 26%) 1.8817\n",
      "17m 59s (- 35m 59s) (25000 33%) 1.7361\n",
      "21m 27s (- 32m 10s) (30000 40%) 1.5839\n",
      "24m 53s (- 28m 26s) (35000 46%) 1.4429\n",
      "28m 18s (- 24m 46s) (40000 53%) 1.2940\n",
      "31m 45s (- 21m 10s) (45000 60%) 1.1935\n",
      "35m 19s (- 17m 39s) (50000 66%) 1.1049\n",
      "38m 52s (- 14m 8s) (55000 73%) 1.0309\n",
      "42m 23s (- 10m 35s) (60000 80%) 0.9482\n",
      "45m 54s (- 7m 3s) (65000 86%) 0.8536\n",
      "49m 29s (- 3m 32s) (70000 93%) 0.8255\n",
      "53m 15s (- 0m 0s) (75000 100%) 0.7671\n"
     ]
    }
   ],
   "source": [
    "hidden_size = 256\n",
    "encoder1 = EncoderRNN(input_lang.n_words, hidden_size).to(device)\n",
    "attn_decoder1 = AttnDecoderRNN(hidden_size, output_lang.n_words, dropout_p=0.1).to(device)\n",
    "\n",
    "trainIters(encoder1, attn_decoder1, 75000, print_every=5000)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "> j y travaille encore .\n",
      "= i m still working on it .\n",
      "< i m still working on it . <EOS>\n",
      "\n",
      "> je suis fatigue de toutes ces reflexions .\n",
      "= i m tired of all this nagging .\n",
      "< i am tired of all this room . <EOS>\n",
      "\n",
      "> vous etes timide n est ce pas ?\n",
      "= you re shy aren t you ?\n",
      "< you re shy aren t you ? <EOS>\n",
      "\n",
      "> je suis pret pour mon prochain defi .\n",
      "= i m ready for my next challenge .\n",
      "< i m ready for my own days . <EOS>\n",
      "\n",
      "> il est tres fier de sa moto trafiquee .\n",
      "= he s very proud of his custom motorcycle .\n",
      "< he is very proud of his parents of success .\n",
      "\n",
      "> vous etes responsable .\n",
      "= you are to blame .\n",
      "< you are early . <EOS>\n",
      "\n",
      "> vous avez tout a fait raison .\n",
      "= you re absolutely right .\n",
      "< you are always right . <EOS>\n",
      "\n",
      "> tu es l ainee .\n",
      "= you re the oldest .\n",
      "< you re the oldest . <EOS>\n",
      "\n",
      "> tu veux juste paraitre diplomate .\n",
      "= you re just being diplomatic .\n",
      "< you re just being . . <EOS>\n",
      "\n",
      "> vous n etes pas le bienvenu ici .\n",
      "= you re not welcome here .\n",
      "< you re not welcome here . <EOS>\n",
      "\n"
     ]
    }
   ],
   "source": [
    "evaluateRandomly(encoder1,  attn_decoder1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4.1 可视化注意力\n",
    "\n",
    "注意机制的一个很有用的特性是其高度可解释的输出。因为它用于对输入序列的特定编码器输出进行加权，所以我们可以想象在每个时间步长看网络最关注的位置。\n",
    "\n",
    "你可以简单地运行`plt.matshow(attentions)` 以将注意力输出显示为矩阵，其中列是输入步骤，行是输出步骤："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x1f84d9075c0>"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\nAABJRU5ErkJggg==\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1f84d9fd6a0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%matplotlib inline\n",
    "output_words, attentions = evaluate(\n",
    "    encoder1, attn_decoder1, \"je suis trop froid .\")\n",
    "plt.matshow(attentions.numpy())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "为了更好地展示结果，我们给轴添加上标签："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "input =  elle a cinq ans de moins que moi .\n",
      "output =  she s five years younger than me . <EOS>\n"
     ]
    },
    {
     "data": {
      "image/png": "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\nrkJggg==\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1f850fdd438>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "input =  elle est trop petit .\n",
      "output =  she is too short . <EOS>\n"
     ]
    },
    {
     "data": {
      "image/png": "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\nkYRzsWnBkAAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1f850fdd9e8>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "input =  je ne crains pas de mourir .\n",
      "output =  i m not dying to die . <EOS>\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1f84f5bb550>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "input =  c est un jeune directeur plein de talent .\n",
      "output =  he is a talented young director . <EOS>\n"
     ]
    },
    {
     "data": {
      "image/png": "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\nGD3e4iCAAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1f84df7fcf8>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "def showAttention(input_sentence, output_words, attentions):\n",
    "    # Set up figure with color bar\n",
    "    fig = plt.figure()\n",
    "    ax = fig.add_subplot(111)\n",
    "    cax = ax.matshow(attentions.numpy(), cmap='bone')\n",
    "    fig.colorbar(cax)\n",
    "    \n",
    "    # Set up axes\n",
    "    ax.set_xticklabels(['']+input_sentence.split(' ')+['<EOS>'], rotation=90)\n",
    "    ax.set_yticklabels(['']+output_words)\n",
    "    \n",
    "    # Show label at every tick\n",
    "    ax.xaxis.set_major_locator(ticker.MultipleLocator(1))\n",
    "    ax.yaxis.set_major_locator(ticker.MultipleLocator(1))\n",
    "    \n",
    "    plt.show()\n",
    "\n",
    "def evaluateAndShowAttention(input_sentence):\n",
    "    output_words, attentions = evaluate(\n",
    "        encoder1, attn_decoder1, input_sentence)\n",
    "    print('input = ', input_sentence)\n",
    "    print('output = ', ' '.join(output_words))\n",
    "    showAttention(input_sentence, output_words, attentions)\n",
    "    \n",
    "evaluateAndShowAttention(\"elle a cinq ans de moins que moi .\")\n",
    "\n",
    "evaluateAndShowAttention(\"elle est trop petit .\")\n",
    "\n",
    "evaluateAndShowAttention(\"je ne crains pas de mourir .\")\n",
    "\n",
    "evaluateAndShowAttention(\"c est un jeune directeur plein de talent .\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python [conda root]",
   "language": "python",
   "name": "conda-root-py"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
